import { Button, Col, Form, Layout, Modal, Row, Space } from "antd";
import React, { useEffect, useReducer } from 'react';
import SelectTable from "../components/SelectTable";
import useDrawer from "../components/useDrawer";
import styles from './common.module.css';

export default function CardTable({ name, parent, filter, form, table, doQuery, doSave, doDelete, doExport, doImport, onSelect, onCheck }) {
  const [drawer, drawerHolder] = useDrawer({
    placement: "right",
  });
  const [state, dispatch] = useReducer((state, action) => {
    switch (action.type) {
      case 'loading':
        return { ...state, loading: true };
      case 'loaded':
        return {
          ...state,
          selected: null,  // 重新加载必须清空当前选中行，因为可能与加载后的新纪录不一致
          checkedRows: [], // 重新加载必须清空当前选中行，因为可能与加载后的新纪录不一致
          loading: false,
          data: action.data,
          pagination: {
            ...state.pagination,
            total: action.total,
            current: Math.min(Math.floor(action.total / state.pagination.pageSize) + 1, state.pagination.current),
          },
        };
      case 'change':
        return {
          ...state,
          filters: { ...state.filters, ...action.filters },
          pagination: action.pagination || state.pagination,
          sorter: action.sorter || state.sorter,
        };
      case 'check':
        return { ...state, checkedRows: action.rows };
      case 'select':
        return { ...state, selected: action.record };
      case 'exporting':
        return { ...state, exporting: true };
      case 'exported':
        return { ...state, exporting: false };
      default:
        return state;
    }
  }, {
    loading: true,
    filters: {},
    sorter: [],
    data: [],
    pagination: {
      showTotal: total => `共${total}条`,
      showSizeChanger: true,
      total: 0,
      pageSize: 10,
      current: 1,
    },
    selected: null,
    checkedRows: [],
    exporting: false,
  });

  useEffect(() => {
    reload();
    // eslint-disable-next-line
  }, [parent, state.filters, state.sorter, state.pagination.current, state.pagination.pageSize]);

  useEffect(() => {
    if (onSelect) onSelect(state.selected);
  }, [onSelect, state.selected]);

  useEffect(() => {
    if (onCheck) onCheck(state.checkedRows);
  }, [onCheck, state.checkedRows]);

  function reload() {
    dispatch({ type: 'loading' });
    // 处理过滤条件
    const filters = [];
    Object.keys(state.filters).forEach(key => {
      if (null == state.filters[key] || '' === state.filters[key]) return;
      filters.push([key, Array.isArray(state.filters[key]) ? 'between' : (typeof state.filters[key] === 'string' ? 'like' : '='), state.filters[key]]);
    });
    const order = {};
    (Array.isArray(state.sorter) ? state.sorter : [state.sorter]).forEach(s => order[s.field] = s.order);

    if (doQuery) {
      doQuery(filters, order, state.pagination.pageSize, state.pagination.current).then(({ Total, Rows }) => {
        dispatch({ type: 'loaded', total: Total, data: Rows });
      });
    } else {
      dispatch({ type: 'loaded', total: 0, data: [] });
    }
  }

  const [edit_form_default] = Form.useForm();
  const edit_form = form.form ?? edit_form_default;
  function edit(record) {
    if (record) {
      edit_form.setFieldsValue(record);
    } else {
      edit_form.resetFields();
      // 查询条件上的值带到编辑表单里
      const filters = {};
      Object.keys(state.filters).forEach(key => {
        filters[key] = Array.isArray(state.filters[key]) ? null : state.filters[key];
      });
      edit_form.setFieldsValue(filters);
    }
    // 打开抽屉
    const handle = drawer.open({
      title: (record ? '修改' : '新增') + name,
      content: (
        <Form form={edit_form} labelCol={{ span: form && form.labelCol ? form.labelCol : 6 }}>
          {form ? form.items.map((item, index) => (
            <div key={index}>{typeof item === 'function' ? item(record, state.selected) : item}</div>
          )) : null}
        </Form>
      ),
      onOk() {
        edit_form.validateFields().then(values => {
          const target = Object.assign({}, record, values);
          if (doSave) {
            doSave(target, state.selected).then(() => {
              handle.destroy();
              reload();
            });
          } else {
            handle.destroy();
          }
        });
      },
    });
  }

  function remove(record) {
    if (!doDelete) return;
    Modal.confirm({
      title: '删除确认',
      content: "数据删除后不可恢复, 请确定",
      onOk() {
        doDelete(record).then(() => reload());
      }
    });
  }

  function export_xls() {
    if (!doExport) return;
    dispatch({ type: 'exporting' });
    const filters = [];
    Object.keys(state.filters).forEach(key => {
      if (state.filters[key] == null) return;
      filters.push([key, Array.isArray(state.filters[key]) ? 'between' : (typeof state.filters[key] === 'string' ? 'like' : '='), state.filters[key]]);
    });
    const order = {};
    (Array.isArray(state.sorter) ? state.sorter : [state.sorter]).forEach(s => order[s.field] = s.order);

    doExport(filters, order).catch(e => alert('导出失败', e.message, { type: 'error' })).then(() => dispatch({ type: 'exported' }));
  }

  function import_xls() {
    if (!doImport) return;
    dispatch({ type: 'exporting' });
    doImport().catch(e => alert('导入失败', e.message, { type: 'error' })).then(() => dispatch({ type: 'exported' })).then(reload);
  }

  const [filter_form_default] = Form.useForm();
  const filter_form = filter.form ?? filter_form_default;
  return (
    <Layout className={styles.container}>
      <Layout.Header className={styles.toolbar}>
        <Form labelCol={{ span: filter && filter.labelCol ? filter.labelCol : 4 }} form={filter_form}
          onFinish={values => dispatch({ type: 'change', filters: values })}>
          <Row gutter={[8, 8]}>
            {filter && filter.items ? filter.items.map((item, index) => {
              const spans = filter.defaultColSpan || { xs: 24, sm: 12, md: 8, xl: 6, xxl: 4 };
              return <Col key={index} {...spans}>{item}</Col>;
            }) : null}
            <Col span={24}>
              <Space>
                <Button htmlType="submit">查询</Button>
                <Button onClick={() => filter_form.resetFields()}>重置</Button>
                {!doSave ? null : <Button type="primary" onClick={() => edit()}>新增</Button>}
                {!doImport ? null : <Button loading={state.exporting} onClick={import_xls}>导入</Button>}
                {!doExport ? null : <Button loading={state.exporting} onClick={export_xls}>导出</Button>}
                {filter ? filter.buttons : null}
              </Space>
            </Col>
          </Row>
        </Form>
      </Layout.Header>
      <Layout.Content>
        <SelectTable loading={state.loading} dataSource={state.data} pagination={state.pagination} showSorterTooltip={false}
          onChange={(pagination, filters, sorter) => dispatch({ type: 'change', pagination, filters, sorter })}
          rowSelection={{
            onSelect: (record, selected, selectedRows) => dispatch({ type: 'check', rows: selectedRows }),
            onSelectAll: (selected, selectedRows) => dispatch({ type: 'check', rows: selectedRows }),
            onSelectNone: () => dispatch({ type: 'check', rows: [] }),
          }}
          onRow={(record) => ({
            onClick: () => dispatch({ type: 'select', record }),
            onDoubleClick: () => !doSave ? null : edit(record),
          })}
          columns={table && table.columns ? [...table.columns.map((c, i) => ({
            ellipsis: true,
            ...c,
            sorter: c.sorter === true ? {
              multiple: i + 1,
            } : c.sorter,
          })), ...(doSave || doDelete ? [{
            title: '操作',
            key: '操作',
            align: 'right',
            width: table.operatorWidth || 80,
            render(record) {
              return (
                <Space style={{ color: '#00bfff', cursor: 'pointer' }}>
                  {table.operators}
                  {!doSave ? null : <span onClick={e => {
                    e.stopPropagation();
                    edit(record);
                  }}>编辑</span>}
                  {!doDelete ? null : <span onClick={e => {
                    e.stopPropagation();
                    remove(record);
                  }} style={{ color: 'red' }}>删除</span>}
                </Space>
              );
            },
          }] : [])] : []} />
      </Layout.Content>
      {drawerHolder}
    </Layout>
  )
}